#include "ThreadPool.hpp"

#include <unistd.h>

namespace se {

ThreadPool::ThreadPool(size_t threadCount, size_t taskQueueCapacity)
: _isExit(false)
, _threadCount(threadCount)
, _taskQueueCapacity(taskQueueCapacity)
, _taskQueue(_taskQueueCapacity) { 
    this->_threads.reserve(this->_threadCount);
}
void ThreadPool::start() {
    for (size_t i = 0; i < this->_threadCount; i++) {
        this->_threads.push_back(std::unique_ptr<Thread>(new Thread([this]() { this->threadFunction(); })));
    }

    for (auto &item : this->_threads) {
        item->start();
    }
}

void ThreadPool::stop() {
    while (!this->_taskQueue.empty()) {
        ::sleep(1);
    }

    this->_isExit = true;
    this->_taskQueue.weakup();
    for (auto &item : this->_threads) {
        item->join();
    }
}

void ThreadPool::addTask(Task task) {
    this->_taskQueue.push(task);
}

ThreadPool::Task ThreadPool::getTask() {
    return this->_taskQueue.pop();
}

ThreadPool::~ThreadPool() {
    this->stop();
}

void ThreadPool::threadFunction() {
    while (!this->_isExit) {
        Task task = this->getTask();
        if (task) {
            task();
        }
    }
}

}  // namespace se